package com.duowan.realtime.hash;

import com.duowan.realtime.server.util.HashUtils;

public class SimpleLcgHashFunction extends AbstractCustomHashFunction {

	@Override
	public int[] hash(byte[] value, int m, int k) {
		setK(k);
		setM(m);
		return hashLCG(value);
	}

	/**
	 * 简单线性同余+Java初始化常数,hash速度快,但散列相对较低
	 * @param value the value to be hashed
	 * @return array with <i>k</i> integer hash positions in the range <i>[0,m)</i>
	 */
	protected int[] hashLCG(byte[] value) {
		// Java constants
		final long multiplier = 0x5DEECE66DL;
		final long addend = 0xBL;
		final long mask = (1L << 48) - 1;

		// Generate int from byte Array using the FNV hash
		int reduced = Math.abs(HashUtils.hashBytes(value));
		// absolute value
		if (reduced == Integer.MIN_VALUE)
			reduced = 42;

		// Calculate k numbers iterativeley
		int[] positions = new int[k];
		long seed = reduced;
		for (int i = 0; i < k; i++) {
			// LCG formula: x_i+1 = (multiplier * x_i + addend) mod mask
			seed = (seed * multiplier + addend) & mask;
			positions[i] = (int) (seed >>> (48 - 30)) % m;
		}
		return positions;
	}
}
